package com.alogic.xscript.plugins;

import com.alogic.xscript.ExecuteWatcher;
import com.alogic.xscript.Logiclet;
import com.alogic.xscript.LogicletContext;
import com.alogic.xscript.doc.XsObject;
import com.alogic.xscript.doc.json.JsonObject;
import com.anysoft.util.BaseException;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import org.apache.commons.lang3.StringUtils;
import org.yaml.snakeyaml.Yaml;

import java.util.Iterator;
import java.util.Map;

/**
 * 从yaml中加载文档
 *
 * @since 1.6.12.27 [20190403 duanyy] <br>
 *
 * @version 1.6.14.16 [20210816 duanyy] <br>
 * - 增加raw和ref参数 <br>
 */
public class FromYaml extends Segment{
    protected String tag = "data";
    protected String content = "";
    protected boolean extend = false;
    protected boolean ref = false;
    protected boolean raw = false;

    protected static ThreadLocal<Yaml> yamlLocal = new ThreadLocal<Yaml>(){
        protected Yaml initialValue() {
            return new Yaml();
        };
    };

    public FromYaml(String tag, Logiclet p) {
        super(tag, p);
    }

    @Override
    public void configure(Properties p){
        super.configure(p);
        tag = PropertiesConstants.getRaw(p,"tag",tag);
        content = PropertiesConstants.getRaw(p,"content","");
        extend = PropertiesConstants.getBoolean(p,"extend",extend,true);
        ref = PropertiesConstants.getBoolean(p,"ref",ref,true);
        raw = PropertiesConstants.getBoolean(p,"raw",raw,true);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void onExecute(XsObject root,
                             XsObject current, LogicletContext ctx,
                             ExecuteWatcher watcher) {
        if (current instanceof JsonObject){
            Map<String,Object> jsonCurrent = (Map<String, Object>) current.getContent();
            String v = ctx.transform(content);
            if (StringUtils.isNotEmpty(v)) {
                if (ref) {
                    if (raw) {
                        v = PropertiesConstants.getRaw(ctx, v, "");
                    }else{
                        v = PropertiesConstants.getString(ctx,v,"");
                    }
                }
            }
            if (StringUtils.isNotEmpty(v)){
                Object template = yamlLocal.get().load(v);
                if (template instanceof Map){
                    if (extend){
                        Map<String,Object> data = (Map<String,Object>)template;
                        Iterator<Map.Entry<String,Object>> iter = data.entrySet().iterator();
                        while (iter.hasNext()){
                            Map.Entry<String,Object> entry = iter.next();
                            jsonCurrent.put(entry.getKey(), entry.getValue());
                        }
                        super.onExecute(root, current, ctx, watcher);
                    }else{
                        String tagValue = ctx.transform(tag);
                        if (StringUtils.isNotEmpty(tagValue)){
                            jsonCurrent.put(tagValue, template);
                            JsonObject newCurrent = new JsonObject(tagValue,(Map<String,Object>)template);
                            super.onExecute(root, newCurrent, ctx, watcher);
                        }
                    }
                }else{
                    String tagValue = ctx.transform(tag);
                    if (StringUtils.isNotEmpty(tagValue)){
                        jsonCurrent.put(tagValue, template);
                    }
                }
            }
        }else{
            throw new BaseException("core.e1000",
                    String.format("Tag %s does not support protocol %s",
                            getXmlTag(),root.getClass().getName()));
        }
    }
}
